package com.sdy.supermarket.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.approval.api.ApprovalAllApi;
import com.sdy.approval.biz.model.TpApproveFlow;
import com.sdy.approval.biz.model.TpApproveFlowConfig;
import com.sdy.approval.biz.model.TpOrder;
import com.sdy.common.model.BizException;
import com.sdy.common.model.FileObj;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.MapUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.fs.api.FsApi;
import com.sdy.mvc.utils.JsonUtil;
import com.sdy.supermarket.biz.mapper.GsOrderItemMapper;
import com.sdy.supermarket.biz.model.GsApp;
import com.sdy.supermarket.biz.model.GsApproveFlow;
import com.sdy.supermarket.biz.model.GsOrder;
import com.sdy.supermarket.biz.mapper.GsOrderMapper;
import com.sdy.supermarket.biz.model.GsOrderApp;
import com.sdy.supermarket.biz.model.GsOrderItem;
import com.sdy.supermarket.biz.model.GsRes;
import com.sdy.supermarket.biz.service.GsAppInterfaceService;
import com.sdy.supermarket.biz.service.GsAppService;
import com.sdy.supermarket.biz.service.GsApproveFlowService;
import com.sdy.supermarket.biz.service.GsOrderAppService;
import com.sdy.supermarket.biz.service.GsOrderItemService;
import com.sdy.supermarket.biz.service.GsOrderService;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import com.sdy.supermarket.biz.service.GsResService;
import com.sdy.supermarket.biz.service.GsUserResService;
import com.sdy.supermarket.biz.utils.PageUtils;
import com.sdy.supermarket.biz.vo.*;
import com.sdy.usercenter.api.UserQueryApi;
import com.sdy.usercenter.api.dto.DeptDto;
import com.sdy.usercenter.api.dto.RoleDto;
import com.sdy.usercenter.api.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源申请表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2019-07-16
 */
@Slf4j
@Service
@SuppressWarnings("unchecked")
public class GsOrderServiceImpl extends BaseServiceImpl<GsOrder> implements GsOrderService {
    @Resource
    private GsOrderMapper gsOrderMapper;
    @Autowired
    private GsOrderItemService gsOrderItemService;
    @Autowired
    private GsResService gsResService;
    @Autowired
    private ApprovalAllApi approvalAllApi;
    @Autowired
    private UserQueryApi userQueryApi;
    @Resource
    private GsOrderItemMapper gsOrderItemMapper;
    @Resource
    private FsApi fsApi;
    @Resource
    private GsOrderAppService gsOrderAppService;
    @Resource
    private GsAppService gsAppService;


    @Override
    public GsOrder getByOrderNo(String orderNo) {
        return getOne(new LambdaQueryWrapper<GsOrder>().eq(GsOrder::getOrderNo, orderNo));
    }

    @Override
    public GsOrder getOrderFullInfo(String orderNo) throws BizException {
        GsOrder order = getOne(new LambdaQueryWrapper<GsOrder>().eq(GsOrder::getOrderNo, orderNo));
        Assert.isNull(order, "订单不存在：" + orderNo);
        List<GsOrderItem> itemList = gsOrderItemService.list(
                new LambdaQueryWrapper<GsOrderItem>()
                        .eq(GsOrderItem::getUserId, order.getUserId())
                        .eq(GsOrderItem::getOrderId, order.getId())
                        .eq(GsOrderItem::getType, 1)
                        .orderByAsc(GsOrderItem::getId)
        );
        specificItemList(itemList);
        order.setItemList(itemList);
        return order;
    }

    @Override
    public GsOrder getUncompletedOrderFullInfo(Integer userId) {
        GsOrder order = new GsOrder();
        order.setUserId(userId).setState(0);
        List<GsOrderItem> itemList = gsOrderItemService.list(
                new LambdaQueryWrapper<GsOrderItem>()
                        .eq(GsOrderItem::getUserId, userId)
                        .eq(GsOrderItem::getType, 2)
                        .isNull(GsOrderItem::getOrderId)
                        .orderByAsc(GsOrderItem::getId)
        );
        specificItemList(itemList);
        List<String> collect = itemList.stream().map(GsOrderItem::getRes).map(ResSimpleVO::getIcon).collect(Collectors.toList());
        List<FileObj> listInfo = fsApi.getFileListInfo(collect);
        for (GsOrderItem item : itemList) {
            for (FileObj file : listInfo) {
                if (item.getRes().getIcon().equals(file.getId())) {
                    item.getRes().setIconInfo(file);
                }
            }
        }
        order.setItemList(itemList);

        return order;
    }

    @Override
    public boolean updateOrderResIdState(String orderId, Integer resId, Integer result) {
        GsOrder gsOrder = gsOrderMapper.selectOne(Wrappers.<GsOrder>lambdaQuery().eq(GsOrder::getOrderNo, orderId).select(GsOrder::getId));
        GsOrderItem gsOrderItem = gsOrderItemMapper.selectOne(Wrappers.<GsOrderItem>lambdaQuery().eq(GsOrderItem::getOrderId, gsOrder.getId()).eq(GsOrderItem::getResId, resId));
        gsOrderItem.setState(result);
        int updateById = gsOrderItemMapper.updateById(gsOrderItem);
        return updateById != 0;
    }

    @Override
    public IPage<ResOrderPgVO> pageOrder(Page<GsOrderItem> page, String orderNo, String resName, Integer state, Integer userId, Integer opUserId, Integer orderState) {
//        TpApproveFlow tpApproveFlow = new TpApproveFlow();
//        tpApproveFlow.setApprovalDeptId(user.getManageDeptId()).setApprovalRoleId(user.getRoleIdList().get(0));
        UserDTO user = userQueryApi.getUser(opUserId);
        Page<TpOrder> pagelist = new Page<>();
        pagelist.setCurrent(page.getCurrent());
        pagelist.setSize(page.getSize());
        // TODO 此处传入的部门列表可能需要传入管理部门的ID
        List<TpOrder> orderFlowList = approvalAllApi.selectTpOrderApprovalByCondition(user.getOwnDeptIdList(), user.getRoleIdList(), state, orderNo, orderState, "[政务超市]");
        List<String> orderItemNo = orderFlowList.stream().map(TpOrder::getApplicationNum).collect(Collectors.toList());
        if (orderFlowList.isEmpty()) {
            return new Page<ResOrderPgVO>(page.getCurrent(), page.getSize(), 0).setRecords(Collections.emptyList());
        }
        IPage<GsOrderItem> itemPage = gsOrderItemService.lambdaQuery()
                .eq(GsOrderItem::getType, 1)
                .in(GsOrderItem::getOrderItemNo, orderItemNo)
                .isNotNull(GsOrderItem::getOrderId)
                .eq(userId != null, GsOrderItem::getUserId, userId)
                .in(GsOrderItem::getState, Arrays.asList(3, 4, 5, 6, 7))
                .like(StringUtil.isNotBlank(resName) && StringUtil.isNotEmpty(resName), GsOrderItem::getResName, resName)
                .like(StringUtil.isNotBlank(orderNo) && StringUtil.isNotEmpty(orderNo), GsOrderItem::getOrderNo, orderNo)
                .orderByDesc(GsOrderItem::getOrderId)
                .isNull(GsOrderItem::getVersionNo)
                .page(page);
        Map<Integer, UserDTO> userMap = Collections.emptyMap();
        Map<Integer, GsOrder> orderMap = Collections.emptyMap();
        if (!itemPage.getRecords().isEmpty()) {
            // 查询用户部门
            List<UserDTO> userList = userQueryApi.listUser(itemPage.getRecords().stream().map(GsOrderItem::getUserId).collect(Collectors.toList()));
            userMap = MapUtil.collectionToMap(userList, UserDTO::getId);
            // 查询原始订单
            Collection<GsOrder> orderList = listByIds(itemPage.getRecords().stream().map(GsOrderItem::getOrderId).collect(Collectors.toList()));
            orderMap = MapUtil.collectionToMap(orderList, GsOrder::getId);
            // 给订单列表设置当前审批的节点部门ID
            List<TpApproveFlow> newFlowInfo = approvalAllApi.selectApprovalFlowByNumOrderList(orderItemNo, user.getOwnDeptIdList(), user.getRoleIdList());
            newFlowInfo.forEach(flow -> {
                itemPage.getRecords().forEach(item -> {
                    if (item.getOrderItemNo().equals(flow.getApplyId())) {
                        item.setFlowState(flow.getResult());
                    }
                });
            });
        }
        List<ResOrderPgVO> voList = new ArrayList<>();
        for (int i = 0; i < itemPage.getRecords().size(); i++) {
            GsOrderItem gsOrderItem = itemPage.getRecords().get(i);
            ResOrderPgVO vo = new ResOrderPgVO();
            vo.setFlowState(gsOrderItem.getFlowState());
            vo.setResNameList(Collections.singletonList(gsOrderItem.getResName()));
            vo.setCreateTime(gsOrderItem.getCreateTime());
            vo.setState(gsOrderItem.getState());
            vo.setItemId(gsOrderItem.getId());
            UserDTO userDTO = userMap.get(gsOrderItem.getUserId());
            GsOrder origin = orderMap.get(gsOrderItem.getOrderId());
            if (origin != null) {
                vo.setContactName(origin.getContactName());
                vo.setContactTel(origin.getContactTel());
                vo.setOrderNo(origin.getOrderNo());
            }
            if (userDTO != null) {
                vo.setUserName(userDTO.getName());
                if (origin != null) {
                    if (origin.getDeptType().equals(1)) {
                        vo.setDeptName(userDTO.getOwnDeptName());
                    } else if (origin.getDeptType().equals(2)) {
                        vo.setDeptName(userDTO.getPartTimeDeptName());
                    }
                }
            }
            voList.add(vo);
        }
        // TODO 此处查询出了所有数据，对数据进行‘假’分页
        PageUtils<ResOrderPgVO> pageData = new PageUtils(page.getSize(), page.getCurrent(), voList);
        return new Page<ResOrderPgVO>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(pageData.getRecords());
    }


    @Override
    public IPage<ResOrderPgVO> pageUserOrder(Page<GsOrderItem> page, String orderNo, String resName, Integer state, Integer userId) {
        UserDTO user = userQueryApi.getUser(userId);
        LambdaQueryWrapper<GsOrderItem> wrapper = Wrappers.<GsOrderItem>lambdaQuery().eq(GsOrderItem::getDeptId, user.getOwnDeptId())
                .isNotNull(GsOrderItem::getOrderId)
                .like(orderNo != null, GsOrderItem::getOrderNo, orderNo)
                .like(StringUtil.isNotBlank(resName) && StringUtil.isNotEmpty(resName), GsOrderItem::getResName, resName)
                .isNull(GsOrderItem::getVersionNo);
        if (null != state && 2 == state) {
            wrapper.in(GsOrderItem::getState, state, 3);
        } else {
            wrapper.eq(state != null, GsOrderItem::getState, state);
        }
        IPage<GsOrderItem> iPage = gsOrderItemService.page(page, wrapper);
        List<GsOrderItem> orderItemList = iPage.getRecords();
        if (orderItemList.size() == 0) {
            return new Page<ResOrderPgVO>(page.getCurrent(), page.getSize(), iPage.getTotal()).setRecords(null).setPages(iPage.getPages());
        }
        List<ResOrderPgVO> resOrderPgVOS = new ArrayList<>();
//        GsOrder gsOrder = gsOrderMapper.selectOne(Wrappers.<GsOrder>lambdaQuery().eq(GsOrder::getOrderNo, orderItemList.get(0).getOrderNo()));
        orderItemList.forEach(gsOrderItem -> {
            resOrderPgVOS.add(new ResOrderPgVO().setUserName(user.getName()).setCreateTime(gsOrderItem.getCreateTime()).setOrderNo(gsOrderItem.getOrderNo())
                    .setItemId(gsOrderItem.getId()).setResName(gsOrderItem.getResName()).setState(gsOrderItem.getState()).setDeptName(user.getOwnDeptName())
                    .setContactName(gsOrderItem.getContactName()).setContactTel(gsOrderItem.getContactTel())
            );
        });
        return new Page<ResOrderPgVO>(page.getCurrent(), page.getSize(), iPage.getTotal()).setRecords(resOrderPgVOS).setPages(iPage.getPages());
    }


    @Override
    public List<GsOrderItem> toConfirmOrder(Integer userId, Integer resId) {
        if (resId == null) {
            List<GsOrderItem> itemList = gsOrderItemService.list(
                    new LambdaQueryWrapper<GsOrderItem>()
                            .eq(GsOrderItem::getUserId, userId)
                            .eq(GsOrderItem::getState, 1)
                            .eq(GsOrderItem::getType, 2)
                            .isNull(GsOrderItem::getOrderId)
                            .orderByAsc(GsOrderItem::getId)
            );
            specificItemList(itemList);
            List<String> collect = itemList.stream().map(GsOrderItem::getRes).map(ResSimpleVO::getIcon).collect(Collectors.toList());
            List<FileObj> listInfo = fsApi.getFileListInfo(collect);
            for (GsOrderItem itemOne : itemList) {
                for (FileObj file : listInfo) {
                    if (itemOne.getRes().getIcon().equals(file.getId())) {
                        itemOne.getRes().setIconInfo(file);
                    }
                }
            }
            return itemList;
        } else {
            GsRes res = gsResService.getById(resId);
            GsOrderItem item = new GsOrderItem()
                    .setState(2)
                    .setType(2)
                    .setContactName("")
                    .setContactTel("")
                    .setRemark("")
                    .setCreateTime(new Date())
                    .setResId(resId)
                    .setResName(res.getName())
                    .setUserId(userId);
            gsOrderItemService.save(item);
            List<GsOrderItem> itemList = new ArrayList<>();
            itemList.add(item);
            specificItemList(itemList);
            List<String> collect = itemList.stream().map(GsOrderItem::getRes).map(ResSimpleVO::getIcon).collect(Collectors.toList());
            List<FileObj> listInfo = fsApi.getFileListInfo(collect);
            for (GsOrderItem itemOne : itemList) {
                for (FileObj file : listInfo) {
                    if (itemOne.getRes().getIcon().equals(file.getId())) {
                        itemOne.getRes().setIconInfo(file);
                    }
                }
            }
            return itemList;
        }
    }

    @Override
    public void approve(GsApproveFlow approveFlow, Integer opUserId, String orderNo) throws Exception {
        Assert.isNull(approveFlow.getApplyId(), "参数错误");
        Assert.isNull(approveFlow.getResult(), "参数错误");
        Assert.isNull(orderNo, "参数错误");
        GsOrderItem orderItem = gsOrderItemService.getById(approveFlow.getApplyId());
        Assert.isNull(orderItem, "getOrderDetail订单数据不存在");
        Assert.isTrue(!orderItem.getState().equals(3) && !orderItem.getState().equals(4), "订单状态不正确1");
        Assert.isTrue(!orderItem.getType().equals(1), "订单状态不正确2");
        approveFlow.setUserId(opUserId);
        approveFlow.setCreateTime(new Date());
        // 审核时暂不需要审核文件
        approveFlow.setFile(JsonUtil.convertFileObjsToJson(approveFlow.getFileObjList()));
        // TODO 此处自己保存的节点信息貌似没有作用，获取订单详情时节点信息都是从流程审批模块获取到的
//        gsApproveFlowService.save(approveFlow);
        if (approveFlow.getResult() == 2 || approveFlow.getResult() == 3) {
            TpApproveFlow tpApproveFlow = new TpApproveFlow();
            tpApproveFlow.setResult(approveFlow.getResult());
            //   ApplyId
            tpApproveFlow.setApplyId(orderNo + "-" + approveFlow.getApplyId());
            tpApproveFlow.setUserId(approveFlow.getUserId());
            tpApproveFlow.setResId("[政务超市]" + orderItem.getResId());
            tpApproveFlow.setAuditOpinion(approveFlow.getRemark());
            UserDTO user = userQueryApi.getUser(opUserId);
            // 如果审批不通过就保留历史信息
            if (approveFlow.getResult() == 3) {
                List<GsOrderItem> versionOrderItem = gsOrderItemMapper.selectList(Wrappers.<GsOrderItem>lambdaQuery().eq(GsOrderItem::getOrderItemNo, orderItem.getOrderItemNo()).isNotNull(GsOrderItem::getVersionNo));
                Integer version = versionOrderItem.size() + 1;
                int insert = gsOrderItemMapper.insert(orderItem.setVersionNo(orderItem.getOrderItemNo() + "-" + version));
                Assert.isTrue(insert == 0, "审核时服务器出现异常，请重试");
            }
            //  审批发送至流程审批模块
            approvalAllApi.updateNodeApprovalResults(tpApproveFlow, user.getOwnDeptIdList(), user.getRoleIdList());
        }

    }

    @Override
    public ResOrderDetailVO getOrderDetail(String orderNo, Integer itemId, Integer userId) throws BizException {
        GsOrder gsOrder = getOne(new LambdaQueryWrapper<GsOrder>().eq(GsOrder::getOrderNo, orderNo));
        Assert.isNull(gsOrder, "订单不存在");
        GsOrderItem orderItem = gsOrderItemService.getById(itemId);
        Assert.isNull(orderItem, "订单不存在");
        Assert.isTrue(!gsOrder.getId().equals(orderItem.getOrderId()), "订单参数错误");
        ResOrderDetailVO vo = new ResOrderDetailVO();
        UserDTO userDTO = userQueryApi.getUser(orderItem.getUserId());
        GsRes res = gsResService.getById(orderItem.getResId());
        List<TpApproveFlow> tpApproveFlows = approvalAllApi.selectApprovalFlowByResId(orderItem.getOrderItemNo());
        // 根据流程审批模块查询到该订单的所有节点信息,并放入返回信息内;
        List<OrderFlowVO> flowVos = new ArrayList<>();
        for (TpApproveFlow tp : tpApproveFlows) {
            flowVos.add(new OrderFlowVO().setCreateTime(tp.getModifyTime()).setFlowState(tp.getFlowAvailable())
                    .setType(tp.getResult()).setOpUserNameId(tp.getModifyUser()).setOpinion(tp.getAuditOpinion()).setOpUserDeptId(tp.getApprovalDeptId()));
        }
        // 配置该页面当前用户是否能够审核 isApprove 字段
        List<TpApproveFlow> newFlowInfo = tpApproveFlows.stream().filter(flow -> flow.getResult() == 1 || flow.getResult() == 3).collect(Collectors.toList());
        if (newFlowInfo.size() != 0) {
            vo.setFlowState(newFlowInfo.get(0).getResult());
        } else {
            vo.setFlowState(3);
        }
        // 根据用户列表和部门列表查询出用户名称和部门名称，然后循环放入需要返回的数据中
        List<Integer> userIdList = tpApproveFlows.stream().map(tp -> tp.getModifyUser()).collect(Collectors.toList());
        if (userIdList.size() != 0) {
            setFlowVoUserName(flowVos, userIdList);
        }
        List<Integer> deptIdList = tpApproveFlows.stream().map(tp -> tp.getApprovalDeptId()).collect(Collectors.toList());
        if (deptIdList.size() != 0) {
            setFlowVoDeptName(flowVos, deptIdList);
        }
        vo.setRemark(orderItem.getRemark());
        vo.setDeptType(orderItem.getDeptType());
        vo.setFlowList(flowVos);
        List<GsOrderApp> orderAppList = gsOrderAppService.lambdaQuery().eq(GsOrderApp::getOrderId, orderItem.getOrderItemNo()).list();
        List<GsApp> appList = gsAppService.lambdaQuery().in(GsApp::getCode, orderAppList.stream().map(GsOrderApp::getAppCode).collect(Collectors.toList())).list();
        Map<String, GsApp> appMap = MapUtil.collectionToMap(appList, GsApp::getCode);
        if (StringUtil.isNotEmpty(orderItem.getEnclosure()) && StringUtil.isNotBlank(orderItem.getEnclosure())) {
            List<FileObj> fileListInfo = fsApi.getFileListInfo(Arrays.asList(orderItem.getEnclosure().split(",")));
            vo.setEnclosures(fileListInfo);
        } else {
            vo.setEnclosures(null);
        }
        vo.setUserName(userDTO.getName());
        vo.setDeptName(userDTO.getOwnDeptName());
        vo.setContactName(orderItem.getContactName());
        vo.setContactTel(orderItem.getContactTel());
        vo.setCreateTime(orderItem.getCreateTime());
        vo.setItemId(itemId);
        vo.setOrderNo(gsOrder.getOrderNo());
        vo.setOrderItemNo(orderItem.getOrderItemNo());
        vo.setState(orderItem.getState());
        vo.setResList(Collections.singletonList(ResSimpleVO.format(res)));
        vo.setAppList(orderAppList.stream().map(item -> new AppIpOrderVO()
                .setAppCode(item.getAppCode())
                .setAppName(appMap.get(item.getAppCode()).getName())
                .setIpList(Arrays.asList(item.getIp().split(",")))).collect(Collectors.toList()));
        if (StringUtil.isNotBlank(gsOrder.getEnclosure())) {
            try {
                vo.setFileObjList(JsonUtil.fromJson(gsOrder.getEnclosure(), List.class));
            } catch (Exception e) {
                log.error("反序列化错误{}", gsOrder.getEnclosure(), e);
            }
        }
        return vo;
    }

    /**
     * 给节点信息列表设置用户名称
     *
     * @param flowVOS
     * @param userIdList
     * @return
     */
    private List<OrderFlowVO> setFlowVoUserName(List<OrderFlowVO> flowVOS, List<Integer> userIdList) {
        List<UserDTO> userDTOS = userQueryApi.listUser(userIdList);
        for (OrderFlowVO flow : flowVOS) {
            for (UserDTO user : userDTOS) {
                if (null != flow.getOpUserNameId() && flow.getOpUserNameId().equals(user.getId())) {
                    flow.setOpUserName(user.getName());
                }

            }
        }
        return flowVOS;
    }

    /**
     * 给节点信息列表设置部门名称
     *
     * @param flowVOS
     * @param deptIdList
     * @return
     */
    private List<OrderFlowVO> setFlowVoDeptName(List<OrderFlowVO> flowVOS, List<Integer> deptIdList) {
        List<DeptDto> deptDtos = userQueryApi.listDeptByIds(deptIdList);
        for (OrderFlowVO flow : flowVOS) {
            for (DeptDto dept : deptDtos) {
                if (flow.getOpUserDeptId().equals(dept.getId())) {
                    if (null != dept.getAbbreviation()) {
                        flow.setOpUserDept(dept.getAbbreviation());
                    } else {
                        flow.setOpUserDept(dept.getName());
                    }
                }
            }
        }
        return flowVOS;
    }

    /**
     * 获取订单行项目明细
     */
    private void specificItemList(List<GsOrderItem> itemList) {
        if (!itemList.isEmpty()) {
            List<Integer> resIdList = itemList.stream().map(GsOrderItem::getResId).collect(Collectors.toList());
            Collection<GsRes> resList = gsResService.listByIds(resIdList);
            Map<Integer, GsRes> resMap = MapUtil.collectionToMap(resList, GsRes::getId);
            itemList.forEach(item -> item.setRes(ResSimpleVO.format(resMap.get(item.getResId()))));
        }
    }
}
